﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Threading;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

using RaisingStudio.SmallProgram.Library.Internal;

namespace RaisingStudio.SmallProgram.Library
{
    [SmallProgramType]
    public static class GraphicsWindow
    {
        static GraphicsWindow()
        {
            _penThickness = 2.0;
            Pen pen = new Pen();
            pen.Brush = Color.Black;
            pen.Thickness = _penThickness;
            _pen = pen;
            _backgroundBrush = Color.White;
            _colorTint = Color.White;
        }

        private static GraphicsGame _game;
        internal static GraphicsGame GraphicsGame
        {
            get
            {
                return _game;
            }
        }

        internal static GraphicsDevice GraphicsDevice
        {
            get
            {
                return _game.GraphicsDevice;
            }
        }


        public static Primitive CanResize
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive FontBold
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive FontItalic
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive FontName
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive FontSize
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive Height
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive LastKey
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive LastText
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive Left
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive MouseX
        {
            get
            {
                return Microsoft.Xna.Framework.Input.Mouse.GetState().X;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive MouseY
        {
            get
            {
                return Microsoft.Xna.Framework.Input.Mouse.GetState().Y;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive Title
        {
            get
            {
                // TODO:
                return null;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive Top
        {
            get
            {
                // TODO:
                return 0;
            }
            set
            {
                // TODO:
            }
        }

        public static Primitive Width
        {
            get
            {
                // TODO:
                return 0;
            }
            set
            {
                // TODO:
            }
        }


        #region Initialize
        internal static bool _windowCreated = false;
        private static bool _gameRunning = false;
        private static object _syncLock = new object();

        private static bool _isHidden;
        internal static bool _windowVisible = false;

        public static void Initialize()
        {
            SignupForWindowEvents();
            SmallProgramApplication.Initialize();
        }

        private static void SignupForWindowEvents()
        {
            // TODO:
            /*
            _shapesCanvas.MouseLeftButtonDown += delegate
            {
                _isLeftMouseButtonDown = true;
                _keyboardControl.Focus();
                _shapesCanvas.CaptureMouse();
                SmallProgramCallback callback = _mouseDown;
                if (callback != null)
                {
                    callback();
                }
            };
            _shapesCanvas.MouseLeftButtonUp += delegate
            {
                _shapesCanvas.ReleaseMouseCapture();
                _isLeftMouseButtonDown = false;
                SmallProgramCallback callback = _mouseUp;
                if (callback != null)
                {
                    callback();
                }
            };
            _shapesCanvas.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                SmallProgramCallback callback = _mouseMove;
                Point position = e.GetPosition(_shapesCanvas);
                _mouseX = position.X;
                _mouseY = position.Y;
                if (callback != null)
                {
                    callback();
                }
            };
            _keyboardControl.KeyDown += delegate(object sender, KeyEventArgs e)
            {
                SmallProgramCallback temp = _keyDown;
                _lastKey = e.Key;
                if (temp != null)
                {
                    BeginInvoke(delegate
                    {
                        temp();
                    });
                }
                SmallProgramCallback temp2 = _textInput;
                if (temp2 != null)
                {
                    BeginInvoke(delegate
                    {
                        temp2();
                    });
                }
            };
            _keyboardControl.KeyUp += delegate(object sender, KeyEventArgs e)
            {
                InvokeHelper invokeDelegate = null;
                SmallProgramCallback temp = _keyUp;
                _lastKey = e.Key;
                if (temp != null)
                {
                    if (invokeDelegate == null)
                    {
                        invokeDelegate = delegate
                        {
                            temp();
                        };
                    }
                    BeginInvoke(invokeDelegate);
                }
            };
             */
        }


        private static void CreateWindow()
        {
            CreateGame();
        }

        private static void CreateGame()
        {
            lock (_syncLock)
            {
                _game = new GraphicsGame();
            }
        }

        internal static void OnGameRun()
        {
            _gameRunning = true;
        }

        private static void RunGame()
        {
            Thread thread = new Thread(delegate()
            {
                if (!_windowCreated)
                {
                    CreateWindow();
                    _windowCreated = true;
                }
                if ((_game != null) && (!_gameRunning))
                {
                    _game.GameStarted += new EventHandler(OnGameStarted);
                    // Run the game.
                    _game.Run();
                }
            });
            //thread.IsBackground = true;
            thread.Start();
            while ((!_windowCreated) || (_game == null) || (!_gameRunning))
            {
                Program.Delay(10);
            }
        }

        private static void OnGameStarted(object sender, EventArgs e)
        {
            OnGameRun();
        }

        internal static void VerifyAccess()
        {
            Show();
        }
        #endregion

        #region event
        private static SmallProgramCallback _keyDown;
        public static event SmallProgramCallback KeyDown
        {
            add
            {
                VerifyAccess();
                _keyDown = null;
                _keyDown += value;
            }
            remove
            {
                _keyDown -= value;
            }
        }

        private static SmallProgramCallback _keyUp;
        public static event SmallProgramCallback KeyUp
        {
            add
            {
                VerifyAccess();
                _keyUp = null;
                _keyUp += value;
            }
            remove
            {
                _keyUp -= value;
            }
        }

        private static SmallProgramCallback _mouseDown;
        public static event SmallProgramCallback MouseDown
        {
            add
            {
                VerifyAccess();
                _mouseDown = null;
                _mouseDown += value;
            }
            remove
            {
                _mouseDown -= value;
            }
        }

        private static SmallProgramCallback _mouseMove;
        public static event SmallProgramCallback MouseMove
        {
            add
            {
                VerifyAccess();
                _mouseMove = null;
                _mouseMove += value;
            }
            remove
            {
                _mouseMove -= value;
            }
        }

        private static SmallProgramCallback _mouseUp;
        public static event SmallProgramCallback MouseUp
        {
            add
            {
                VerifyAccess();
                _mouseUp = null;
                _mouseUp += value;
            }
            remove
            {
                _mouseUp -= value;
            }
        }

        private static SmallProgramCallback _textInput;
        public static event SmallProgramCallback TextInput
        {
            add
            {
                VerifyAccess();
                _textInput = null;
                _textInput += value;
            }
            remove
            {
                _textInput -= value;
            }
        }
        #endregion

        #region Pen & Brush
        internal static Pen _pen;
        private static double _penThickness;
        internal static Color _backgroundBrush;
        internal static Color _fillBrush;
        internal static Color _colorTint;

        public static Primitive PenColor
        {
            get
            {
                return (string)InvokeWithReturn(delegate
                {
                    return _pen.Brush.ToString();
                });
            }
            set
            {
                BeginDrawInvoke(delegate
                {
                    _pen.Brush = ColorConverter.GetColor((string)value);
                });
            }
        }

        public static Primitive PenWidth
        {
            get
            {
                return _penThickness;
            }
            set
            {
                _penThickness = (double)value;
                BeginDrawInvoke(delegate
                {
                    _pen.Thickness = _penThickness;
                });
            }
        }

        public static Primitive BackgroundColor
        {
            get
            {
                return (string)InvokeWithReturn(delegate
                {
                    return _backgroundBrush.ToString();
                });
            }
            set
            {
                BeginInvoke(delegate
                {
                    _backgroundBrush = ColorConverter.GetColor((string)value);
                });
            }
        }

        public static Primitive BrushColor
        {
            get
            {
                return (string)InvokeWithReturn(delegate
                {
                    return _fillBrush.ToString();
                });
            }
            set
            {
                BeginInvoke(delegate
                {
                    _fillBrush = ColorConverter.GetColor((string)value);
                });
            }
        }
        #endregion

        public static void Clear()
        {
            VerifyAccess();
            Invoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }


        public static void DrawBoundText(Primitive x, Primitive y, Primitive width, Primitive text)
        {
            // TODO:
        }

        public static void DrawEllipse(Primitive x, Primitive y, Primitive width, Primitive height)
        {
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }

        public static void DrawImage(Primitive imageName, Primitive x, Primitive y)
        {
            InvokeHelper invokeDelegate = null;
            Texture2D image;
            if (!imageName.IsEmpty)
            {
                VerifyAccess();
                image = ImageList.GetBitmap(imageName);
                if (image != null)
                {
                    if (invokeDelegate == null)
                    {
                        invokeDelegate = delegate
                        {
                            // TODO: DrawImage
                        };
                    }
                    BeginDrawInvoke(invokeDelegate);
                }
            }
        }

        public static void DrawLine(Primitive x1, Primitive y1, Primitive x2, Primitive y2)
        {
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
                GraphicsGame.DrawingContext.DrawLine(x1, y1, x2, y2, Color.Black);
            });
        }

        public static void DrawRectangle(Primitive x, Primitive y, Primitive width, Primitive height)
        {
            // TODO:
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }

        public static void DrawResizedImage(Primitive imageName, Primitive x, Primitive y, Primitive width, Primitive height)
        {
            InvokeHelper invokeDelegate = null;
            Texture2D image;
            if (!imageName.IsEmpty)
            {
                VerifyAccess();
                image = ImageList.GetBitmap(imageName);
                if (image != null)
                {
                    if (invokeDelegate == null)
                    {
                        invokeDelegate = delegate
                        {
                            // TODO: 
                        };
                    }
                    BeginDrawInvoke(invokeDelegate);
                }
            }
        }

        public static void DrawText(Primitive x, Primitive y, Primitive text)
        {
            // TODO:
        }

        public static void DrawTriangle(Primitive x1, Primitive y1, Primitive x2, Primitive y2, Primitive x3, Primitive y3)
        {
            // TODO:
        }

        public static void FillEllipse(Primitive x, Primitive y, Primitive width, Primitive height)
        {
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }

        public static void FillRectangle(Primitive x, Primitive y, Primitive width, Primitive height)
        {
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }

        public static void FillTriangle(Primitive x1, Primitive y1, Primitive x2, Primitive y2, Primitive x3, Primitive y3)
        {
            VerifyAccess();
            BeginInvoke(delegate
            {
                // TODO: _pen.Thickness
            });
        }

        #region Color
        public static Primitive GetColorFromRGB(Primitive red, Primitive green, Primitive blue)
        {
            int num = System.Math.Abs((int)(red % 0x100));
            int num2 = System.Math.Abs((int)(green % 0x100));
            int num3 = System.Math.Abs((int)(blue % 0x100));
            return string.Format("#{0:X2}{1:X2}{2:X2}", num, num2, num3);
        }

        private static Random _random;

        public static Primitive GetRandomColor()
        {
            if (_random == null)
            {
                _random = new Random((int)DateTime.Now.Ticks);
            }
            return string.Format("#{0:X2}{1:X2}{2:X2}", _random.Next(0x100), _random.Next(0x100), _random.Next(0x100));
        }
        #endregion

        #region Pixel
        public static Primitive GetPixel(Primitive x, Primitive y)
        {
            // TODO:
            return null;
        }

        public static void SetPixel(Primitive x, Primitive y, Primitive color)
        {
            // TODO:
        }
        #endregion

        #region Show & Hide
        public static void Show()
        {
            // TODO:
            RunGame();
        }

        public static void Hide()
        {
            // TODO:
        }
        #endregion

        public static void ShowMessage(Primitive text, Primitive title)
        {
            // TODO:
        }


        internal static void Invoke(InvokeHelper invokeDelegate)
        {
            SmallProgramApplication.Invoke(invokeDelegate);
        }

        internal static void BeginInvoke(InvokeHelper invokeDelegate)
        {
            SmallProgramApplication.BeginInvoke(invokeDelegate);
        }

        internal static void BeginDrawInvoke(InvokeHelper invokeDelegate)
        {
            //(new Thread(delegate()
            //{
            invokeDelegate();
            //})).Start();
        }

        internal static object InvokeWithReturn(InvokeHelperWithReturn invokeDelegate)
        {
            return SmallProgramApplication.InvokeWithReturn(invokeDelegate);
        }

        internal class Pen
        {
            public Color Brush
            {
                get;
                set;
            }

            public double Thickness
            {
                get;
                set;
            }
        }
    }
}

